package ThreadSafety;

public class Wait {
    public static void main(String[] args) throws InterruptedException{
        Object object = new Object();
//        synchronized (object) {
//            System.out.println("wait之前!");
//            //wait不加任何条件就会死等,直到被唤醒
//            //虽然这里的wait是阻塞得,阻塞在synchronized代码快里,实际上这里的代码块是释放了锁的,此时其他的线程可以获取object这个对象的锁
//            //此时这里的阻塞就处在waiting状态
//            object.wait();
//            System.out.println("wait之后");
//        }
        /**   wait和notify的对象得配对,如果wait使用的对象和notify使用的对象不一样,
         *    此时notify不会有任何效果(notify只能唤醒在同一个对象上等待的线程)
         */
        Thread t1 = new Thread(() -> {
            System.out.println("t1 wait 之前!");
            synchronized (object) {
                try {
                    object.wait(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("t1 wait 之后");
        });
        Thread t2 = new Thread(() -> {
            System.out.println("t2 notify 之前!");
            //notify这个操作也是要进行加锁的
            synchronized (object) {
                //只要没有notify之前,那么就会一直阻塞
                try {
                    Thread.sleep(50000);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                object.notify();
            }
            System.out.println("t2 notify 之后");
        });
        //这里的两个线程的启动,并不能确定一定是t1先执行,因为线程调度的不确定性,所以可能是先进行唤醒,在进行wait,此时还是处在阻塞状态中
        t1.start();
        //因此要保证t1先执行,可以阻塞一会,但是这个只是大概率会让t1先执行,如果出现极端情况,比如电脑卡顿,就可能出现线程的调度时间超过sleep的时间
        //此时t2还是可能先执行
        Thread.sleep(500);
        t2.start();
    }
}
